/*
+--------------------------
| FreeloaderOS v0.0.1
|  - Microkernel
+--------------------------
| Written by Alec Hussey
| Copyright (c) 2007
|  - Deus X Foundation
+---------------------------
*/

/*
 * Memory Test
 */

unsigned long memtest_databus(volatile unsigned long *address)
{
	unsigned long pattern;
	
	for (pattern = 0x00000001; pattern != 0x00000000; pattern <<= 1)
	{
		*address = pattern;
		
		if (*address != pattern)
			return pattern;
	}
	
	return 0;
}

unsigned long *memtest_addrbus(unsigned long *base_addr, unsigned long num_bytes)
{
	unsigned long pattern = 0xAAAAAAAA;
	unsigned long antipattern = 0x55555555;
	unsigned long bitmask = (num_bytes - 1) >> 2;
	unsigned long offset, test_offset;
	
	for (offset = 0x00000001; (offset & bitmask) != 0; offset <<= 1)
		base_addr[offset] = pattern;
	
	test_offset = 0;
	base_addr[test_offset] = antipattern;
	
	for (offset = 0x00000001; (offset & bitmask) != 0; offset <<= 1)
	{
		if (base_addr[offset] != pattern)
			return &baseAddress[testOffset];
	}
	
	for (test_offset = 0x00000001; (test_offset & bitmask) != 0; test_offset <<= 1)
	{
		base_addr[test_offset] = antipattern;
    	
		for (offset = 0x00000001; (offset & bitmask) != 0; offset <<= 1)
		{
    		if ((base_addr[offset] != pattern) && (offset != test_offset))
    			return &base_addr[test_offset];
		}
    	
		base_addr[test_offset] = pattern;
	}
	
	return 0;
}

unsigned long *memtest_device(unsigned long *base_addr, unsigned long num_bytes)
{
	unsigned long num_longs = num_bytes / 4;
	unsigned long pattern;
	unsigned long antipattern;
	unsigned long offset;
	
	for (pattern = 1, offset = 0; offset < num_longs; pattern++, offset++)
		base_addr[offset] = pattern;
	
	for (pattern = 1, offset = 0; offset < num_longs; pattern++, offset++)
	{
		if (base_addr[offset] != pattern)
			return &base_addr[offset];
		
		antipattern = ~pattern;
		base_addr[offset] = antipattern;
	}
	
	for (pattern = 1, offset = 0; offset < num_longs; pattern++, offset++)
	{
		antipattern = ~pattern;
		
		if (baseAddress[offset] != antipattern)
			return &base_addr[offset];
		
		base_addr[offset] = 0;
	}
	
	return 0;
}
